package control;

import exceptions.*;
import java.util.ArrayList;
import services.*;
import util.EnumSearchParameter;
import vo.*;

/**
 *
 * @author sbaldrich
 */
public class Controller {

    private static Controller INSTANCE;

    private Controller() {
    }

    ;

    public static Controller getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Controller();
        }
        return INSTANCE;
    }
    private static UserService us;

    private static UserService getUserService() {
        if (us == null) {
            us = new UserService();
        }
        return us;
    }
    private static ContestService cs;

    private static ContestService getContestService() {
        if (cs == null) {
            cs = new ContestService();
        }
        return cs;
    }
    private static ProblemService ps;

    private static ProblemService getProblemService() {
        if (ps == null) {
            ps = new ProblemService();
        }
        return ps;
    }
    private static TestcaseService ts;

    private static TestcaseService getTestcaseService() {
        if (ts == null) {
            ts = new TestcaseService();
        }
        return ts;
    }
    private static KeywordService ks;

    private static KeywordService getKeywordService() {
        if (ks == null) {
            ks = new KeywordService();
        }
        return ks;
    }
    private static SubmissionService ss;

    private static SubmissionService getSubmissionService() {
        if (ss == null) {
            ss = new SubmissionService();
        }
        return ss;
    }

    /*
     * User Services
     */
    public boolean login(String handle, String password) throws Exception {
        us = getUserService();
        VOUser user;
        try {
            user = us.find(handle);
            if (user.getPassword().compareTo(password) == 0) {
                return true;
            }
            return false;
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return false;
        }
    }

    public boolean register(VOUser vo) throws Exception {
        us = getUserService();
        try {
            us.save(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean registerForContest(String handle, String contestCode) throws Exception {
        cs = getContestService();
        try {
            cs.addUser(contestCode, handle);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean editUser(VOUser vo) throws Exception {
        us = getUserService();
        try {
            us.update(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean deleteUser(VOUser vo) throws Exception {
        us = getUserService();
        try {
            us.delete(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public VOUser findUser(String handle) throws Exception {
        us = getUserService();
        try {
            return us.find(handle);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public ArrayList<VOUser> listUsers(EnumSearchParameter parameter, String value) throws Exception {
        us = getUserService();
        try {
            return us.findAll(parameter, value);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public ArrayList<VOUser> listUsers() throws Exception {
        us = getUserService();
        try {
            return us.findAll();
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public boolean isUserRegistered(String handle , String contestCode)throws Exception
    {
        try {

            return us.isUserInContest(handle , contestCode);

        } catch (Exception e) {
            throw e;
        }
    }

    /*
     * End User services
     */

    /*
     * Contest Services
     */
    public boolean createContest(VOContest vo) throws Exception {
        cs = getContestService();
        try {
            cs.save(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean editContest(VOContest vo) throws Exception {
        cs = getContestService();
        try {
            cs.update(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean deleteContest(VOContest vo) throws Exception {
        cs = getContestService();
        try {
            cs.delete(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public VOContest findContest(String contestCode) throws Exception {
        cs = getContestService();
        try {
            return cs.find(contestCode);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public boolean endContest(String contestCode) throws Exception {
        cs = getContestService();
        try {
            cs.endContest(contestCode);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public ArrayList<VOScoreboard> getScoreBoard(String contestCode) throws Exception {
        cs = getContestService();
        try {
            return cs.getScoreboard(contestCode);
        } catch (Exception e) {
            throw e;
        }
    }

    public ArrayList<VOContest> listContests() throws Exception {
        cs = getContestService();
        try {
            return cs.findAll();
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
        }
        return null;
    }

    public ArrayList<VOContest> listContests(EnumSearchParameter parameter, String value) throws Exception {
        cs = getContestService();
        try {
            return cs.findAll(parameter, value);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
        }
        return null;
    }


    /*
     * End Contest services
     */

    /*
     * Problem Services
     */
    public boolean createProblem(VOProblem vo) throws Exception {
        ps = getProblemService();
        try {
            ps.save(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean deleteProblem(VOProblem vo) throws Exception {
        ps = getProblemService();
        try {
            ps.delete(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public VOProblem findProblem(String problemCode) throws Exception {
        ps = getProblemService();
        try {
            return ps.find(problemCode);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public boolean editProblem(VOProblem vo) throws Exception {
        ps = getProblemService();
        try {
            ps.update(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public ArrayList<VOProblem> listProblems() throws Exception {
        ps = getProblemService();
        try {
            return ps.findall();
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public ArrayList<VOProblem> listProblems(EnumSearchParameter parameter , String value) throws Exception {

        ps = getProblemService();
        try {
            return ps.findall(parameter , value);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    private void createTestcase(VOTestcase tc) throws Exception {
        ts = getTestcaseService();
        try {
            ts.save(tc);
        } catch (Exception e) {
            throw e;
        }
    }

    /*
     * End Problem services
     */

    /*
     * Keyword services
     */
    public boolean createKeyword(VOKeyword vo) throws Exception {
        ks = getKeywordService();
        try {
            ks.save(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean deleteKeyword(VOKeyword vo) throws Exception {
        ks = getKeywordService();
        try {
            ks.delete(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean editKeyword(VOKeyword vo) throws Exception {
        ks = getKeywordService();
        try {
            ks.update(vo);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    public ArrayList<VOKeyword> listKeywords() throws Exception {
        try {
            return ks.findAll();
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }
    }

    public boolean addKeywordToProblem(String keyword, String problemcode) throws Exception {
        ks = getKeywordService();
        try {
            ks.addToProblem(keyword, problemcode);
            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    /*
     * End Keyword services
     */
    /*
     * Submission services
     */
    public boolean submit(VOSubmission vo) throws Exception {
        ss = getSubmissionService();
        try {
            ss.processSubmission(vo);
            return true;
        } catch (Exception e) {
            if (e instanceof DatabaseException
                    || e instanceof CompilationException) {
                throw e;
            }
            return false;
        }
    }

    public ArrayList<VOSubmission> listSubmissions(EnumSearchParameter parameter, Object vo) throws Exception {
        ss = getSubmissionService();
        try {
            return ss.findAll(parameter, vo);
        } catch (Exception e) {
            if (e instanceof DatabaseException) {
                throw e;
            }
            return null;
        }

    }

    /*
     * End Submission services
     */
    public static void main(String[] args)throws Exception {
        Controller c = Controller.getInstance();
        cs = getContestService();
        ps = getProblemService();
        c.deleteProblem(ps.find("PCODE"));
//        ArrayList<VOProblem> l = c.listProblems();
//        for(VOProblem v : l)
//            System.out.println("ProblemCode :  " + v.getProblemCode());
        us = getUserService();
        VOUser u = us.find("SBaldrich");
//        VOContest ct = cs.find("CODE");
//        u.setCountry("LOCOCCOMBIA");
//        ct.setName("NEW NAME");
//        c.editUser(u);
//        c.editContest(ct);
        ArrayList<VOProblem> l = c.listProblems(EnumSearchParameter.CONTEST, "CODE");
        for(VOProblem v : l)
            System.out.println(v.getName());

//        VOSubmission s = new VOSubmission();
//         String code = "#include <iostream>\n"+
//                            "using namespace std;\n"+
//                            "int main()\n"+
//                            "{for(int i = 0; i < 0; ++i ){++i;--i;++i;--i;if(i%10000000 != 0 )cout << i << endl;} \n"+
//                               "\tint a , b , c;\n"+
//                               "\tcin >> a >> b >> c;\n"+
//                               "\tcout << a + b + c <<endl;int cc = 3.3;cc >?= 32;\n"+
//                               "\treturn 0;\n"+
//                            "}\n";
//        s.setCode(code);
//        s.setProblemCode("PCODE");
//        s.setLanguage("CPP");
//        s.setUserHandle("SBaldrich");
//        s.setContestCode("CODE");
//
//        try {
//            c.submit(s);
//
//        } catch (Exception e) {
//            System.out.println("Exception: " + e.getMessage());
//        }
//
//
    }
}
